提升

# 提升

我们习惯将 var a = 2; 看作一个声明,而实际上 JavaScript 引擎并不这么认为。它将 var a和 a = 2 当作两个单独的声明,第一个是编译阶段的任务,而第二个则是执行阶段的任务。

这意味着无论作用域中的声明出现在什么地方,都将在代码本身被执行前首先进行处理。 可以将这个过程形象地想象成所有的声明(变量和函数)都会被“移动”到各自作用域的 最顶端,这个过程被称为提升。

如下:

    "use strict"
    a = 2;
    console.log(a);
    var a;

上述代码会输出什么? 因为是严格模式,所以并不会在全局作用域声明同名变量,有的开发者会认为 Reference Error,但实际上输出 2

    console.log(a)
    var a = 2;

这个又输出什么呢? 应该是 undefined

大概的原理就是,编译器会将 声明和赋值 分开处理。 用 var a = 10; 举例 它会被拆分成 var a; a = 10; 然后 先进性 var a 也就是声明变量 a 此时 a 为 undefined,表示作用域中已经存在这个变量了,然后当读到前面的 var a = 10; 这行代码时,在进行剩下的赋值操作。

先有声明,然后赋值

只有声明本身会被提升,而赋值或其他运行逻辑会留在 原地 。如果提升改变了代码执行的顺序,会造成非常严重的破坏。

函数声明也会被提升

  foo()
  
  function foo(){
    console.log(1);
  }

但是请注意!!! 函数表达式不会被提升!

  foo();
  var foo = function (){
    console.log(1)
  }

为什么呢? 我们 var 声明的变量的初始值是 undefined,函数声明的值是 function(){} 也就是说 当 foo 执行的时候 foo 为 undefined 我们对 undefined() 调用。 TypeError。他会告诉你 foo 不是 function

如果 var 声明 和 函数声明 声明的是同一个会发生什么?

console.log(foo);

var foo;
function foo() {
    console.log(2);
}

我们发现打印结果是 foo 函数,调换他们的位置,发现结果是相同的。 函数声明和变量声明都会被提升。 函数会首先被提升,然后才是变量。

在看下面

function foo() {
    console.log(2);
}

var foo;
console.log(foo);

如果只是在函数后声明了变量,但没有赋值,foo 还是函数。